#include "threadpool.h"
#include <functional>
#include <thread>
#include "Log.h"
#include <iostream>
const int TASK_MAX_THRESHHOLD = 1024;
ThreadPool::ThreadPool() : _initThreadSize(0),
                           _taskSize(0),
                           _taskQueMaxThreshHold(TASK_MAX_THRESHHOLD),
                           _poolMode(PoolMode::MODE_FIXED)
{
}

ThreadPool::~ThreadPool()
{
}

void ThreadPool::setMode(PoolMode mode) // 设置线程的工作模式
{
    _poolMode = mode;
}

// 设   置task任务队列上限的阈值
void ThreadPool::setTaskQueMaxThreshHold(int threshhold)
{
    _taskQueMaxThreshHold = threshhold;
}
class Result;

// 给线程池提交任务
Result ThreadPool::submitTask(std::shared_ptr<Task> sp)
{
    //  获取锁
    std::unique_lock<std::mutex> lock(_taskQueMtx);
    // 线程通信 等待任务队列有空余
    // while(_taskQue.size() == _taskQueMaxThreshHold){
    //     _notFull.wait(lock);
    // }

    // 阻塞时间不能超过1s，超过就返回提交任务失败
    // condition_variable的wait wait_for wait_until
    if (!_notFull.wait_for(lock, std::chrono::seconds(1),
                           [&]() -> bool
                           { return _taskQue.size() < _taskQueMaxThreshHold; }))
    {
        // 此时返回值是false，表示1s过后，条件仍然不满足
        std::cerr << "task Queue is full, submit task fail!" << std::endl;
        return Result(sp, false);
    }

    // 如果有空余，把任务放入任务队列中
    _taskQue.emplace(sp);
    _taskSize++;

    // 通知因为新放了任务，任务队列肯定不空，在_notEmpty上通知
    _notEmpty.notify_all();

    // 返回任务的result对象
    return Result(sp, true);
}

void ThreadPool::start(int initThreadSize) // 开始线程池
{
    // 记录线程初始线程的数量
    _initThreadSize = initThreadSize;

    // 创建线程对象
    for (int i = 0; i < _initThreadSize; i++)
    {
        // 传递智能指针。
        std::unique_ptr<Thread> ptr = std::make_unique<Thread>(std::bind(&ThreadPool::threadFunc, this));
        _threads.emplace_back(std::move(ptr));
    }

    // 启动所有线程
    for (int i = 0; i < _initThreadSize; i++)
    {
        _threads[i]->start();
    }
}

// 从任务队列取出任务进行消费
void ThreadPool::threadFunc()
{

    // std::cout << "begin ThreadFunc" << " ";
    // std::cout << std::this_thread::get_id() << " ";
    // std::cout << "end ThreadFunc" << std::endl;

    while (true)
    {
        LOG(DEBUG, "try to get task");
        std::shared_ptr<Task> task = nullptr;
        {
            // 获取锁
            std::unique_lock<std::mutex> lock(_taskQueMtx);

            // 等待到非空
            _notEmpty.wait(lock, [&]() -> bool
                           { return _taskQue.size() > 0; });

            // 从任务队列取出任务
            task = _taskQue.front();
            LOG(DEBUG, "get task success");

            _taskQue.pop();
            _taskSize--;

            // 取出任务以后，如果还有其他线程，通知其他线程
            if (_taskQue.size() > 0)
            {
                _notEmpty.notify_all();
            }
            // 取出一个任务进行通知，可以继续生产任务了
            _notFull.notify_all();
        }
        // 代码运行到了这里就说明锁释放了。

        // 当前线程负责执行这个任务。
        if (task != nullptr)
        {
            LOG(DEBUG, "begin to handle task");

            task->run();
        }
    }
}

//----------------------------------------------------------------------------------------
// 线程方法实现

Thread::Thread(ThreadFunc func)
    : _func(func) {}
Thread::~Thread() {}
void Thread::start()
{
    std::thread t(_func);
    t.detach(); //
}

////////////
// Result方法的实现
Result::Result(std::shared_ptr<Task> task, bool isValid) : _task(task),
                                                           _isValid(isValid)
{
}
